package com.shinhye.mobilelottery.engine;

import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;

import org.apache.commons.codec.digest.DigestUtils;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import android.util.Xml;

import com.shinhye.mobilelottery.ConstantValue;
import com.shinhye.mobilelottery.net.HttpClientUtils;
import com.shinhye.mobilelottery.net.protocol.Message;
import com.shinhye.mobilelottery.utils.DES;

/**
 * A base engine to handle operation. Every engine implementations should extend from this class.
 * @author ShinHye
 * 2014-9-23 下午7:33:57
 */
public class BaseEngine {

	/**
	 * Send a xml to the server and get a result from the server. In this method we also do some judge to affirm that if the data from server has been balefully changed.
	 * @param xml What to send to the server
	 * @return A result message. If there is an Internet error or data is not match with the original data, it will return null.
	 */
	public Message getResult(String xml) {
		// 步骤二：发送xml文件到服务器端
		// 1、NetUtil判断网络（不在该处使用）
		// 2、HttpUtil创建，sendxml方法（xml）
		// 3、对回复的内容进行判断（非null）
		HttpClientUtils client = new HttpClientUtils();
		InputStream is = client.sendXml(ConstantValue.LOTTERY_URI, xml);
		
		// 步骤三：回复数据处理——校验数据
		// 1、简单校验（equal：防君子）
		// 2、MD5数据的比对
		// MD5比对的思路：与解密无关，在手机端重新加密一次MD5
		// 关键条件：服务器端使用的MD5加密的原始数据是否能够还原
		// MD5原始数据组成：时间戳+代理密码+完整明文的body
		// 时间戳:解析服务器端回复的xml文件
		// 代理密码：常量中存储
		// 完整的明文的body：body里面的数据解密（DES），拼装body标签
		if(is != null) {
			Message res = new Message();
			
			XmlPullParser parser = Xml.newPullParser();
			try {
				parser.setInput(is, ConstantValue.ENCODING);
				int type = parser.getEventType();
				while(type != XmlPullParser.END_DOCUMENT) {
					switch(type) {
					case XmlPullParser.START_TAG:
						if("timestamp".equals(parser.getName())) {
							res.getHeader().getTimestamp().setValue(parser.nextText());
						} else if("digest".equals(parser.getName())) {
							res.getHeader().getDigest().setValue(parser.nextText());
						} else if("body".equals(parser.getName())) {
							res.getBody().setBodyInfo(parser.nextText());
						}
						break;
					}
					type = parser.next();
				}
				
			} catch (Exception e) {
				e.printStackTrace();
			}
			
			// 在手机端生成新的MD5值
			// 与服务器端回复的xml文件中的MD5进行比对
			// 如果通过了
			DES des = new DES();
			String wholebody = "<body>" + des.authcode(res.getBody().getBodyInfo(), "ENCODE", ConstantValue.DES_KEY) + "</body>";
			String beforeMd5 = res.getHeader().getTimestamp().getValue() + ConstantValue.AGENT_PASSWORD + wholebody;
			String md5Hex = DigestUtils.md5Hex(beforeMd5);
			
			if(res.getHeader().getDigest().getValue().equals(md5Hex)) {
				return res;
			}
		}
		return null;
	}
	
	/**
	 * Handle the OElement node and save the error code and the error message into the given Message.
	 * @param res A Message what to save error info.
	 * @param wholebody Body part of the XML
	 * @throws XmlPullParserException
	 * @throws IOException
	 */
	public void handleOElement(Message res, String wholebody) throws XmlPullParserException, IOException {
		StringReader reader = new StringReader(wholebody);
		XmlPullParser parser = Xml.newPullParser();
		parser.setInput(reader);
		int type = parser.getEventType();
		while(type != XmlPullParser.END_DOCUMENT) {
			switch(type) {
			case XmlPullParser.START_TAG:
				if("errorcode".equals(parser.getName())) {
					res.getBody().getOelement().setErrorcode(parser.nextText());
				} else if("errormsg".equals(parser.getName())) {
					res.getBody().getOelement().setErrormsg(parser.nextText());
				}
				break;
			}
			type = parser.next();
		}
		
	}
}
